﻿#region LGPL License

/*
OpenSearchNet
Copyright (c) 2014, Brad Hards <bradh@frogmouth.net>, All rights reserved.

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3.0 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library.
*/

#endregion LGPL License

using System.Collections.Generic;

namespace OpenSearch
{
    /// <summary>
    /// Query from an OpenSearch Description Document
    /// </summary>
    public class Query
    {
        private Dictionary<OpenSearch.NameSpacedParameter, string> searchParameters = new Dictionary<OpenSearch.NameSpacedParameter, string>();

        internal Query(System.Xml.XmlTextReader reader)
        {
            string defaultNamespace = reader.NamespaceURI;
            for (int i = 0; i < reader.AttributeCount; ++i)
            {
                reader.MoveToAttribute(i);
                string attributeName = reader.Name;
                string attributeValue = reader.Value;
                IDictionary<string, string> namespaces = reader.GetNamespacesInScope(System.Xml.XmlNamespaceScope.ExcludeXml);
                searchParameters.Add(new NameSpacedParameter(attributeName, namespaces, defaultNamespace), attributeValue);
            }
        }

        internal Query(System.Xml.XmlElement element)
        {
            foreach (System.Xml.XmlAttribute attribute in element.Attributes)
            {
                searchParameters.Add(new NameSpacedParameter(attribute.LocalName, attribute.NamespaceURI, element.NamespaceURI), attribute.Value);
            }
        }

        /// <summary>
        /// Value representing the "searchTerms" as an OpenSearch 1.1 parameter
        /// </summary>
        public string SearchTerms
        {
            get
            {
                return GetExtendedAttribute(Constants.NSOpenSearch, "searchTerms");
            }
        }

        /// <summary>
        /// Value representing the "title" as an OpenSearch 1.1 parameter
        /// </summary>
        /// <remarks>
        /// <para>
        /// "A human-readable plain text string describing the search request".
        /// </para>
        /// <para>
        /// The OpenSearch specification requires that this contains 256 or fewer characters of plain text.
        /// The value must not contain HTML or other markup. Those constraints are not enforced by this class.
        /// </para>
        /// <para>
        /// This attribute is optional - the server does not need to provide it. This property will return an
        /// empty string if the attribute is not present.
        /// </para>
        /// </remarks>
        public string Title
        {
            get
            {
                return GetExtendedAttribute(Constants.NSOpenSearch, "title");
            }
        }

        /// <summary>
        /// String identifying how the search client should interpret the search request defined by this Query.
        /// </summary>
        /// <remarks>
        /// <para>
        /// Role values are broken down into local role values (implicitly in the OpenSearch 1.1 namespace) and fully
        /// qualified role values (which must be explicitly included in some other namespace). The local roles are:
        /// <list type="">
        /// <item><c>request</c> - Represents the search query that can be performed to retrieve the same set of search results.</item>
        /// <item><c>example</c> - Represents a search query that can be performed to demonstrate the search engine.</item>
        /// <item><c>related</c> - Represents a search query that can be performed to retrieve similar but different search results.</item>
        /// <item><c>correction</c> - Represents a search query that can be performed to improve the result set, such as with a spelling correction.</item>
        /// <item><c>subset</c> - Represents a search query that will narrow the current set of search results.</item>
        /// <item><c>superset</c> - Represents a search query that will broaden the current set of search results.</item>
        /// </list>
        /// </para>
        /// </remarks>
        public string Role
        {
            get
            {
                return GetExtendedAttribute(Constants.NSOpenSearch, "role");
            }
        }

        /// <summary>
        /// Extension mechanism to support lookup of arbitrary extension attributes
        /// </summary>
        /// <param name="parameterNamespace">Namespace of the extended attribute</param>
        /// <param name="parameterName">Name of the extended attribute parameter</param>
        /// <returns>Value of the extended attribute as a string, or null if attribute was not found</returns>
        public string GetExtendedAttribute(string parameterNamespace, string parameterName)
        {
            foreach (NameSpacedParameter key in searchParameters.Keys)
            {
                if ((key.Namespace == parameterNamespace) && (key.Parameter == parameterName))
                {
                    return searchParameters[key];
                }
            }
            return null;
        }

        /// <summary>
        /// Collection of extended attributes
        /// </summary>
        /// <remarks>
        /// <para>
        /// Use this to determine the names of the attributes available. Use <c>GetExtendedAttribute</c>
        /// to retrieve the value for the specific attribute.
        /// </para>
        /// </remarks>
        public ICollection<NameSpacedParameter> ExtendedAttributes
        {
            get
            {
                return searchParameters.Keys;
            }
        }
    }
}